home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / haeberli / libcan / canundo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  4.4 KB  |  207 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *    canundo -
  19.  *        Support undo on canvases.
  20.  *
  21.  *                Paul Haeberli - 1993
  22.  *
  23.  *    exports
  24.  *
  25.     void freeundo(c)
  26.     void addundo(c)
  27.  
  28.     void saverect(c,r)
  29.     void undopaint(c)
  30.     void clearundo(c)
  31.  *
  32.  */
  33. #include "stdio.h"
  34. #include "canvas.h"
  35. #include "chunkarena.h"
  36.  
  37. unsigned long *chunkalloc();
  38.  
  39. static chunkarena *undoarena;
  40.  
  41. void freeundo(c)
  42. canvas *c;
  43. {
  44.     undobuf *u;
  45.     int n;
  46.     unsigned long **lptr;
  47.  
  48.     u = c->undo;
  49.     if(!u)
  50.     return;
  51.     n = u->xsize*u->ysize;
  52.     lptr = u->data;
  53.     while(n--) {
  54.     if(*lptr)
  55.         chunkfree(undoarena,*lptr);
  56.     lptr++;
  57.     }
  58.     myfree(u->data);
  59.     myfree(u);
  60.     c->undo = 0;
  61. }
  62.  
  63. void addundo(c)
  64. canvas *c;
  65. {
  66.     undobuf *u;
  67.     
  68.     u = (undobuf*)mymalloc(sizeof(undobuf));
  69.     u->xsize = ((c->xsize-1)/UNDOTILE)+1;
  70.     u->ysize = ((c->ysize-1)/UNDOTILE)+1;
  71.     u->data = (unsigned long **)mymalloc(u->xsize*u->ysize*sizeof(long*));
  72.     bzero(u->data,u->xsize*u->ysize*sizeof(long*));
  73.     c->undo = u;
  74.     if(!undoarena) 
  75.     undoarena = newchunkalloc(UNDOTILE*UNDOTILE*sizeof(long));
  76. }
  77.  
  78. static unsigned long *canvastile(c,tx,ty)
  79. canvas *c;
  80. int tx, ty;
  81. {
  82.     unsigned long *dptr, *sptr, *ret;
  83.     int iy, cx, cy, nx, ny;
  84.  
  85.     ret = dptr = chunkalloc(undoarena);
  86.     cx = UNDOTILE*tx;
  87.     cy = UNDOTILE*ty;
  88.     sptr = c->data+(cy*c->xsize+cx);
  89.     if((cx+UNDOTILE)<=c->xsize && (cy+UNDOTILE)<=c->ysize) {
  90.     for(iy=0; iy<UNDOTILE; iy++) {
  91.         bcopy(sptr,dptr,UNDOTILE*sizeof(long));
  92.         sptr += c->xsize;
  93.         dptr += UNDOTILE;
  94.     }
  95.     } else {
  96.     nx = c->xsize-cx;
  97.     if(nx>UNDOTILE) nx = UNDOTILE;
  98.     ny = c->ysize-cy;
  99.     if(ny>UNDOTILE) ny = UNDOTILE;
  100.     for(iy=0; iy<ny; iy++) {
  101.         bcopy(sptr,dptr,nx*sizeof(long));
  102.         sptr += c->xsize;
  103.         dptr += UNDOTILE;
  104.     }
  105.     }
  106.     return ret;
  107. }
  108.  
  109. void saverect(c,r)
  110. canvas *c;
  111. rct *r;
  112. {
  113.     undobuf *u;
  114.     int tx, tx1, tx2;
  115.     int ty, ty1, ty2;
  116.     rct srct;
  117.  
  118.     u = c->undo;
  119.     if(!u)
  120.     return;
  121.     if(!rctinter(&c->area,r,&srct))
  122.     return;
  123.     tx1 = srct.xmin/UNDOTILE;
  124.     tx2 = srct.xmax/UNDOTILE;
  125.     ty1 = srct.ymin/UNDOTILE;
  126.     ty2 = srct.ymax/UNDOTILE;
  127.     if(tx2>=u->xsize || ty2>=u->ysize) {
  128.     fprintf(stderr,"Blody heck\n");
  129.     return;
  130.     }
  131.     for(ty=ty1; ty<=ty2; ty++) {
  132.     for(tx=tx1; tx<=tx2; tx++) {
  133.         if(u->data[ty*u->xsize+tx] == 0) 
  134.         u->data[ty*u->xsize+tx] = canvastile(c,tx,ty);
  135.       }
  136.     }
  137. }
  138.  
  139. void undopaint(c)
  140. canvas *c;
  141. {
  142.     undobuf *u;
  143.     unsigned long *dptr, *sptr, *cantile;
  144.     int iy, cx, cy, nx, ny;
  145.     int tx, ty;
  146.     rct r;
  147.  
  148.     u = c->undo;
  149.     if(!u)
  150.     return;
  151.     for(ty=0; ty<u->ysize; ty++) {
  152.     for(tx=0; tx<u->xsize; tx++) {
  153.         sptr = u->data[ty*u->xsize+tx];
  154.         if(sptr) {
  155.         r.xmin = (tx+0)*UNDOTILE;
  156.         r.xmax = (tx+1)*UNDOTILE;
  157.         r.ymin = (ty+0)*UNDOTILE;
  158.         r.ymax = (ty+1)*UNDOTILE;
  159.         markdirty(c,&r,1);
  160.         cantile = canvastile(c,tx,ty);
  161.         cx = UNDOTILE*tx;
  162.         cy = UNDOTILE*ty;
  163.         dptr = c->data+(cy*c->xsize+cx);
  164.         if((cx+UNDOTILE)<=c->xsize && (cy+UNDOTILE)<=c->ysize) {
  165.             for(iy=0; iy<UNDOTILE; iy++) {
  166.             bcopy(sptr,dptr,UNDOTILE*sizeof(long));
  167.             dptr += c->xsize;
  168.             sptr += UNDOTILE;
  169.             }
  170.         } else {
  171.             nx = c->xsize-cx;
  172.             if(nx>UNDOTILE) nx = UNDOTILE;
  173.             ny = c->ysize-cy;
  174.             if(ny>UNDOTILE) ny = UNDOTILE;
  175.             for(iy=0; iy<ny; iy++) {
  176.             bcopy(sptr,dptr,nx*sizeof(long));
  177.             dptr += c->xsize;
  178.             sptr += UNDOTILE;
  179.             }
  180.         }
  181.             chunkfree(undoarena,u->data[ty*u->xsize+tx]);
  182.         u->data[ty*u->xsize+tx] = cantile;
  183.         }
  184.     }
  185.     }
  186.     flushcanvas(c);
  187. }
  188.  
  189. void clearundo(c)
  190. canvas *c;
  191. {
  192.     undobuf *u;
  193.     int tx, ty;
  194.  
  195.     u = c->undo;
  196.     if(!u)
  197.     return;
  198.     for(ty=0; ty<u->ysize; ty++) {
  199.     for(tx=0; tx<u->xsize; tx++) {
  200.         if(u->data[ty*u->xsize+tx]) {
  201.         chunkfree(undoarena,u->data[ty*u->xsize+tx]);
  202.         u->data[ty*u->xsize+tx] = 0;
  203.         }
  204.     }
  205.     }
  206. }
  207.